package com.mezz.bones.framework.mybatis.dynamic.service;

import com.baomidou.dynamic.datasource.creator.DataSourceCreator;
import com.baomidou.dynamic.datasource.creator.DataSourceProperty;
import com.baomidou.dynamic.datasource.creator.hikaricp.HikariCpConfig;
import com.baomidou.dynamic.datasource.spring.boot.autoconfigure.DynamicDataSourceProperties;
import com.mezz.bones.framework.base.domain.enums.ResponseCode;
import com.mezz.bones.framework.base.exception.BaseException;
import com.mezz.bones.framework.mybatis.dynamic.domain.dto.DynamicDataSourceInfo;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;

import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.SQLException;

@Service
@AllArgsConstructor
@Slf4j
public class DataSourceCreatorService {

    private final DataSourceCreator dataSourceCreator;
    private final DynamicDataSourceProperties dataSourceProperties;
    public DataSource createDatasource(DynamicDataSourceInfo dataSourceInfo) {
        // 创建数据源属性
        DataSourceProperty property = new DataSourceProperty();
        property.setUrl(dataSourceInfo.getUrl());
        property.setUsername(dataSourceInfo.getUsername());
        property.setPassword(dataSourceInfo.getPassword());
        property.setDriverClassName(dataSourceInfo.getDriverClassName());
        property.setLazy(dataSourceProperties.getLazy());

        // 应用全局Hikari配置
        // 创建新实例并复制全局配置
        // 后续如果有需要 可以为每个不同的数据源配置不同的连接池属性
        HikariCpConfig instanceConfig = new HikariCpConfig();
        HikariCpConfig globalHikariConfig = dataSourceProperties.getHikari(); // 获取全局配置
        if (globalHikariConfig != null) {
            // 复制全局配置到实例配置
            BeanUtils.copyProperties(globalHikariConfig, instanceConfig);
        }
        property.setHikari(instanceConfig);

        // 创建数据源并验证连接
        DataSource dataSource = dataSourceCreator.createDataSource(property);

        // 验证数据源连接是否有效
        try (Connection connection = dataSource.getConnection()) {
            if (!connection.isValid(5)) {
                //记录日志 详细的链接失败的 参数
                log.error("数据源连接验证失败, url:{}, username:{}", dataSourceInfo.getUrl(), dataSourceInfo.getUsername());
                throw new IllegalStateException("数据源连接验证失败");
            }
        } catch (SQLException e) {
            throw new BaseException(ResponseCode.SYS_ERROR,e.getMessage());
        }

        return dataSource;
    }
}
